package com.ruoyi.factorydata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.factorydata.domain.MaterialCategory;
import com.ruoyi.factorydata.domain.MaterialData;
import com.ruoyi.factorydata.domain.ProductionBom;
import com.ruoyi.factorydata.domain.ProductionBomMaterial;
import com.ruoyi.factorydata.domain.dto.ProductionBomDTO;
import com.ruoyi.factorydata.domain.vo.MaterialDataVo;
import com.ruoyi.factorydata.domain.vo.ProductionBomMaterialVo;
import com.ruoyi.factorydata.domain.vo.ProductionBomVo;
import com.ruoyi.factorydata.mapper.ProductionBomMapper;
import com.ruoyi.factorydata.mapper.ProductionBomMaterialMapper;
import com.ruoyi.factorydata.service.IMaterialCategoryService;
import com.ruoyi.factorydata.service.IMaterialDataService;
import com.ruoyi.factorydata.service.IProductionBomService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 产品bomService业务层处理
 *
 * @author ruoyi
 * @date 2025-07-20
 */
@Slf4j
@Service
public class ProductionBomServiceImpl extends ServiceImpl<ProductionBomMapper, ProductionBom> implements IProductionBomService {
    @Autowired
    private ProductionBomMapper productionBomMapper;

    @Autowired
    private ProductionBomMaterialMapper productionBomMaterialMapper;

    @Autowired
    private IMaterialDataService materialDataService;

    @Autowired
    private IMaterialCategoryService materialCategoryService;

    /**
     * 查询产品bom
     *
     * @param id 产品bom主键
     * @return 产品bom
     */
    @Override
    public ProductionBomVo selectProductionBomById(Long id) {
        ProductionBom productionBom = productionBomMapper.selectProductionBomById(id);
        ProductionBomMaterial productionBomMaterial = new ProductionBomMaterial();
        productionBomMaterial.setProductionBomId(id);
        List<ProductionBomMaterial> productionBomMaterials = productionBomMaterialMapper.selectProductionBomMaterialList(productionBomMaterial);
        List<ProductionBomMaterialVo> productionBomMaterialVos = productionBomMaterials.stream().map(item -> {
            MaterialData materialData = materialDataService.selectMaterialDataById(item.getMaterialId());
            MaterialCategory materialCategory = materialCategoryService.selectMaterialCategoryById(materialData.getCategoryId());
            return ProductionBomMaterialVo.builder()
                    .id(item.getId())
                    .Level(1)
                    .productionBomId(item.getProductionBomId())
                    .materialId(item.getMaterialId())
                    .materialCode(item.getMaterialCode())
                    .materialName(item.getMaterialName())
                    .materialType(item.getMaterialType())
                    .materialTypeName(item.getMaterialTypeName())
                    .materialCategoryId(materialCategory.getId())
                    .materialCategoryName(materialCategory.getMaterialCategoryName())
                    .manufacturingMethod(item.getManufacturingMethod())
                    .manufacturingMethodName(item.getManufacturingMethodName())
                    .materialUnit(item.getMaterialUnit())
                    .materialUnitName(item.getMaterialUnitName())
                    .materialSpecification(materialData.getMaterialSpecification())
                    .usedQuantity(item.getUsedQuantity())
                    .createBy(item.getCreateBy())
                    .createTime(item.getCreateTime())
                    .updateTime(item.getUpdateTime())
                    .build();
        }).collect(Collectors.toList());
        MaterialData materialData = materialDataService.selectMaterialDataById(productionBom.getMaterialId());
        MaterialCategory materialCategory = materialCategoryService.selectMaterialCategoryById(materialData.getCategoryId());
        return ProductionBomVo.builder()
                .id(productionBom.getId())
                .Level(0)
                .materialId(productionBom.getMaterialId())
                .materialCode(productionBom.getMaterialCode())
                .materialName(productionBom.getMaterialName())
                .materialType(productionBom.getMaterialType())
                .materialTypeName(productionBom.getMaterialTypeName())
                .materialCategoryId(materialCategory.getId())
                .materialCategoryName(materialCategory.getMaterialCategoryName())
                .manufacturingMethod(productionBom.getManufacturingMethod())
                .manufacturingMethodName(productionBom.getManufacturingMethodName())
                .materialUnit(productionBom.getMaterialUnit())
                .materialUnitName(productionBom.getMaterialUnitName())
                .materialSpecification(materialData.getMaterialSpecification())
                .demandQuantity(productionBom.getDemandQuantity())
                .createBy(productionBom.getCreateBy())
                .createTime(productionBom.getCreateTime())
                .updateTime(productionBom.getUpdateTime())
                .productionBomMaterials(productionBomMaterialVos)
                .build();
    }

    @Override
    public List<ProductionBomVo> selectProductionBomListByMaterialId(Long materialId) {
        List<ProductionBom> productionBoms = productionBomMapper.selectOneLevelBomListById(materialId);
        List<ProductionBomVo> productionBomVos = new ArrayList<>();
        if(!productionBoms.isEmpty()){
            productionBomVos = productionBoms.stream().map(productionBom -> {
                ProductionBomMaterial productionBomMaterial = new ProductionBomMaterial();
                productionBomMaterial.setProductionBomId(productionBom.getId());
                List<ProductionBomMaterial> productionBomMaterials = productionBomMaterialMapper.selectProductionBomMaterialList(productionBomMaterial);
                List<ProductionBomMaterialVo> productionBomMaterialVos = productionBomMaterials.stream().map(item -> {
                    MaterialData materialData = materialDataService.selectMaterialDataById(item.getMaterialId());
                    MaterialCategory materialCategory = materialCategoryService.selectMaterialCategoryById(materialData.getCategoryId());
                    return ProductionBomMaterialVo.builder()
                            .id(item.getId())
                            .Level(1)
                            .productionBomId(item.getProductionBomId())
                            .materialId(item.getMaterialId())
                            .materialCode(item.getMaterialCode())
                            .materialName(item.getMaterialName())
                            .materialType(item.getMaterialType())
                            .materialTypeName(item.getMaterialTypeName())
                            .materialCategoryId(materialCategory.getId())
                            .materialCategoryName(materialCategory.getMaterialCategoryName())
                            .manufacturingMethod(item.getManufacturingMethod())
                            .manufacturingMethodName(item.getManufacturingMethodName())
                            .materialUnit(item.getMaterialUnit())
                            .materialUnitName(item.getMaterialUnitName())
                            .materialSpecification(materialData.getMaterialSpecification())
                            .usedQuantity(item.getUsedQuantity())
                            .createBy(item.getCreateBy())
                            .createTime(item.getCreateTime())
                            .updateTime(item.getUpdateTime())
                            .build();
                }).collect(Collectors.toList());
                MaterialData materialData = materialDataService.selectMaterialDataById(productionBom.getMaterialId());
                MaterialCategory materialCategory = materialCategoryService.selectMaterialCategoryById(materialData.getCategoryId());
                return ProductionBomVo.builder()
                        .id(productionBom.getId())
                        .Level(0)
                        .materialId(productionBom.getMaterialId())
                        .materialCode(productionBom.getMaterialCode())
                        .materialName(productionBom.getMaterialName())
                        .materialType(productionBom.getMaterialType())
                        .materialTypeName(productionBom.getMaterialTypeName())
                        .materialCategoryId(materialCategory.getId())
                        .materialCategoryName(materialCategory.getMaterialCategoryName())
                        .manufacturingMethod(productionBom.getManufacturingMethod())
                        .manufacturingMethodName(productionBom.getManufacturingMethodName())
                        .materialUnit(productionBom.getMaterialUnit())
                        .materialUnitName(productionBom.getMaterialUnitName())
                        .materialSpecification(materialData.getMaterialSpecification())
                        .demandQuantity(productionBom.getDemandQuantity())
                        .createBy(productionBom.getCreateBy())
                        .createTime(productionBom.getCreateTime())
                        .updateTime(productionBom.getUpdateTime())
                        .productionBomMaterials(productionBomMaterialVos)
                        .build();
            }).collect(Collectors.toList());
        }

        return productionBomVos;
    }

    /**
     * 查询产品bom列表
     *
     * @param productionBom 产品bom
     * @return 产品bom
     */
    @Override
    public List<ProductionBomVo> selectProductionBomList(ProductionBom productionBom) {
        List<ProductionBom> productionBoms = productionBomMapper.selectProductionBomList(productionBom);
        List<ProductionBomVo> productionBomVos = productionBoms.stream().map(item -> {
            ProductionBomMaterial productionBomMaterial = new ProductionBomMaterial();
            productionBomMaterial.setProductionBomId(item.getId());
            List<ProductionBomMaterial> productionBomMaterials = productionBomMaterialMapper.selectProductionBomMaterialList(productionBomMaterial);
            // 设置层级
            List<ProductionBomMaterialVo> productionBomMaterialVos = productionBomMaterials.stream().map(item1 -> {
                MaterialData materialData = materialDataService.selectMaterialDataById(item1.getMaterialId());
                MaterialCategory materialCategory = materialCategoryService.selectMaterialCategoryById(materialData.getCategoryId());
                return ProductionBomMaterialVo.builder()
                        .id(item1.getId())
                        .Level(1)
                        .productionBomId(item1.getProductionBomId())
                        .materialId(item1.getMaterialId())
                        .materialCode(item1.getMaterialCode())
                        .materialName(item1.getMaterialName())
                        .materialType(item1.getMaterialType())
                        .materialTypeName(item1.getMaterialTypeName())
                        .materialCategoryId(materialCategory.getId())
                        .materialCategoryName(materialCategory.getMaterialCategoryName())
                        .manufacturingMethod(item1.getManufacturingMethod())
                        .manufacturingMethodName(item1.getManufacturingMethodName())
                        .materialUnit(item1.getMaterialUnit())
                        .materialUnitName(item1.getMaterialUnitName())
                        .materialSpecification(materialData.getMaterialSpecification())
                        .usedQuantity(item1.getUsedQuantity())
                        .delFlag(item1.getDelFlag())
                        .version(item1.getVersion())
                        .createBy(item1.getCreateBy())
                        .createTime(item1.getCreateTime())
                        .updateBy(item1.getUpdateBy())
                        .updateTime(item1.getUpdateTime())
                        .build();
            }).collect(Collectors.toList());
            MaterialData materialData = materialDataService.selectMaterialDataById(item.getMaterialId());
            MaterialCategory materialCategory = materialCategoryService.selectMaterialCategoryById(materialData.getCategoryId());
            return ProductionBomVo.builder()
                    .id(item.getId())
                    .Level(0)
                    .materialId(item.getMaterialId())
                    .materialCode(item.getMaterialCode())
                    .materialName(item.getMaterialName())
                    .materialType(item.getMaterialType())
                    .materialTypeName(item.getMaterialTypeName())
                    .materialCategoryId(materialCategory.getId())
                    .materialCategoryName(materialCategory.getMaterialCategoryName())
                    .manufacturingMethod(item.getManufacturingMethod())
                    .manufacturingMethodName(item.getManufacturingMethodName())
                    .materialUnit(item.getMaterialUnit())
                    .materialUnitName(item.getMaterialUnitName())
                    .materialSpecification(materialData.getMaterialSpecification())
                    .demandQuantity(item.getDemandQuantity())
                    .status(item.getStatus())
                    .createBy(item.getCreateBy())
                    .createTime(item.getCreateTime())
                    .updateTime(item.getUpdateTime())
                    .productionBomMaterials(productionBomMaterialVos)
                    .build();
        }).collect(Collectors.toList());
        Page<ProductionBom> queryData=(Page<ProductionBom>)productionBoms;
        Page<ProductionBomVo> page = new Page<>(queryData.getPageNum(), queryData.getPageSize());
        page.setTotal(queryData.getTotal());
        page.addAll(productionBomVos);
        return page;
    }

    /**
     * 新增产品bom
     *
     * @param productionBomDTO 产品bom
     * @return 结果
     */
    @Transactional
    @Override
    public int insertProductionBom(ProductionBomDTO productionBomDTO) {
        MaterialData materialData = new MaterialData();
        materialData.setId(productionBomDTO.getMaterialId());
        List<MaterialDataVo> materialDataVos = materialDataService.selectMaterialDataList(materialData);
        int i = 0;
        if (!materialDataVos.isEmpty()) {
            MaterialDataVo materialDataVo = materialDataVos.get(0);
            ProductionBom productionBom = new ProductionBom();
            productionBom.setMaterialId(materialDataVo.getId());
            productionBom.setMaterialCode(materialDataVo.getMaterialCode());
            productionBom.setMaterialName(materialDataVo.getMaterialName());
            productionBom.setMaterialType(materialDataVo.getMaterialType());
            productionBom.setMaterialTypeName(materialDataVo.getMaterialTypeName());
            productionBom.setManufacturingMethod(materialDataVo.getManufacturingMethod());
            productionBom.setManufacturingMethodName(materialDataVo.getManufacturingMethodName());
            productionBom.setMaterialUnit(Optional.ofNullable(materialDataVo.getMaterialUnit()).map(Object::toString).orElse( null));
            productionBom.setMaterialUnitName(materialDataVo.getMaterialUnitName());
            productionBom.setDemandQuantity(productionBomDTO.getDemandQuantity());
            productionBom.setCreateBy(productionBomDTO.getCreateBy());
            productionBom.setCreateTime(DateUtils.getNowDate());
            i = productionBomMapper.insertProductionBom(productionBom);
            if (i > 0) {
                log.info("productionBom:{}", productionBom);
                productionBomDTO.getProductionBomMaterials().forEach(productionBomMaterial -> {
                    productionBomMaterial.setProductionBomId(productionBom.getId());
                    productionBomMaterial.setCreateBy(productionBomDTO.getCreateBy());
                    productionBomMaterial.setCreateTime(DateUtils.getNowDate());
                    productionBomMaterialMapper.insertProductionBomMaterial(productionBomMaterial);
                });
            }
        }

        return i;
    }

    /**
     * 修改产品bom
     *
     * @param productionBomDTO 产品bom
     * @return 结果
     */
    @Transactional
    @Override
    public int updateProductionBom(ProductionBomDTO productionBomDTO) {
        MaterialData materialData = new MaterialData();
        materialData.setId(productionBomDTO.getMaterialId());
        List<MaterialDataVo> materialDataVos = materialDataService.selectMaterialDataList(materialData);
        int i = 0;
        if (!materialDataVos.isEmpty()) {
            MaterialDataVo materialDataVo = materialDataVos.get(0);
            ProductionBom productionBom = new ProductionBom();
            productionBom.setId(productionBomDTO.getId());
            productionBom.setMaterialId(materialDataVo.getId());
            productionBom.setMaterialCode(materialDataVo.getMaterialCode());
            productionBom.setMaterialName(materialDataVo.getMaterialName());
            productionBom.setMaterialType(materialDataVo.getMaterialType());
            productionBom.setMaterialTypeName(materialDataVo.getMaterialTypeName());
            productionBom.setManufacturingMethod(materialDataVo.getManufacturingMethod());
            productionBom.setManufacturingMethodName(materialDataVo.getManufacturingMethodName());
            productionBom.setMaterialUnit(Optional.ofNullable(materialDataVo.getMaterialUnit()).map(Object::toString).orElse( null));
            productionBom.setMaterialUnitName(materialDataVo.getMaterialUnitName());
            productionBom.setDemandQuantity(productionBomDTO.getDemandQuantity());
            productionBom.setUpdateTime(DateUtils.getNowDate());
            i = productionBomMapper.updateProductionBom(productionBom);
            if (i > 0) {
                int delete = productionBomMaterialMapper.delete(new QueryWrapper<ProductionBomMaterial>().lambda()
                        .eq(ProductionBomMaterial::getProductionBomId, productionBomDTO.getId()));
                log.info("productionBom:{}", productionBom);
                productionBomDTO.getProductionBomMaterials().forEach(productionBomMaterial -> {
                    productionBomMaterial.setId(null);
                    productionBomMaterial.setProductionBomId(productionBom.getId());
                    productionBomMaterial.setCreateBy(productionBomDTO.getCreateBy());
                    productionBomMaterial.setCreateTime(DateUtils.getNowDate());
                    productionBomMaterialMapper.insertProductionBomMaterial(productionBomMaterial);
                });
            }
        }

        return i;
    }

    /**
     * 批量删除产品bom
     *
     * @param ids 需要删除的产品bom主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deleteProductionBomByIds(Long[] ids) {
        int i = productionBomMapper.deleteBatchIds(Arrays.stream(ids).collect(Collectors.toList()));
        if (i > 0) {
            int delete = productionBomMaterialMapper.delete(new QueryWrapper<ProductionBomMaterial>().lambda()
                    .in(ProductionBomMaterial::getProductionBomId, ids));
        }
        return i;
    }

    /**
     * 删除产品bom信息
     *
     * @param id 产品bom主键
     * @return 结果
     */
    @Override
    public int deleteProductionBomById(Long id) {
        return productionBomMapper.deleteProductionBomById(id);
    }
}